#pragma once 
#include <iostream>
#include <sys/epoll.h>
#include <string>
#include <cstring>
#include "Err.hpp"
#include "Log.hpp"
const int size = 128;//epoll_create使用，大于0即可
class Epoll
{
public:
    Epoll()
        :_epfd(-1)
    {}
    ~Epoll()
    {
        if(_epfd >= 0)
        {
            close(_epfd);
        }
    }
public:
    void Create();
    bool AddEvent(int sock, uint32_t events);
    int Wait(struct epoll_event revs[], int num, int timeout);
    void Close();
    bool Control(int sock, uint32_t event, int action); 
private:
    int _epfd;
};

void Epoll::Create()
{
    _epfd = epoll_create(size);
    if(_epfd < 0)//创建epoll模型失败
    {
        LogMessage(FATAL, "epoll_create error, code: %d, errstring: %s",errno, strerror(errno));
        exit(EPOLL_CREATE_ERR);
    }
}
bool Epoll::AddEvent(int sock, uint32_t events)//用户到内核
{
    struct epoll_event ev;
    ev.events = events;
    ev.data.fd = sock;
    int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sock, &ev);
    return n == 0;
}
int Epoll::Wait(struct epoll_event revs[], int num, int timeout)//revs是就绪的事件,num表示最多可以存储多少个就绪事件，均为输出型参数
{
    int n = epoll_wait(_epfd, revs, num, timeout);
    return n;//返回就绪事件的个数
}
void Epoll::Close()
{
    if(_epfd >= 0)
    {
        close(_epfd);
    }
}
bool Epoll::Control(int sock, uint32_t event, int action)
{
    bool n = 0;
    if (action == EPOLL_CTL_MOD)
    {
        struct epoll_event ev;
        ev.events = event;
        ev.data.fd = sock;
        n = epoll_ctl(_epfd, action, sock, &ev);
    }
    else if (action == EPOLL_CTL_DEL)
    {
        n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sock, nullptr);
    }
    else { n = -1; }
    return n == 0;
}


